[HEADER]
  .bits 32
  .end
  
[VARS]
  *NULL 0
  *BIOS_SPACE 1
  *KERNEL_SPACE 3
  *USER_SPACE 4
  .end
  
[CODE]
  .userSpacePrint:
    ! userSpacePrint(%a0)
	
	_sl_	
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }else{$__VM_HT->{__VM_Registry}->{__vmY} += 15;}
	  
	  $ht->{__VM_Registry}->{msg}->y($__VM_HT->{__VM_Registry}->{__vmY});
	  $ht->{__VM_Registry}->{msg}->write_to($__VM_SDL_SCREEN, $regs->{a0});
	  $__VM_SDL_SCREEN->update();
	  
	  print "\e[33m[USERSPACE] ".$regs->{a0}."\e[31m\n";
	_end_
	
	ret
	.stop
	
  .returnToBIOSSpace:
    ! returnToBIOSSpace(void)
	_sl_
	  $__vmRingMode = 1;
	_end_
	
	ret
	.stop
	
  .print:
    ! print(%a0)
    call vm_7614t
	
	ret
	.stop

  .verbose:
    ! verbose(%a0)
	_sl_
	  print $regs->{a0}."\n";
	_end_
	
	ret
    .stop

  .main:
    ! main(void)
	loadd %r0 "We're in ring 1, or BIOS code space!"
	
	mov %a0 %r0
	call print
	call verbose
	free %a0
	
	loadd %r0 "Attempting to move into KERNEL code space (ring 3)..."
	
	mov %a0 %r0
	call print
	call verbose
	free %a0
	
	movv %a0 *KERNEL_SPACE
	
	push0x03 %a0
	int 0x03
	pop0x03 %s0
	
	loadi %i0 -1
	cmp %i0 %s0
	  loadd %r0 "Failed to move into KERNEL code space (ring 3)!"
	  
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
	scmp
	cmpf
	  loadi %f0 -1
	scmp
	
	cmp %f0 %i0
	  loadd %r0 "Got a good report; checking ring mode..."
	  
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
	  
	  _sl_
	    if($__vmRingMode == 3){
		  $regs->{s0} = 1;
		}else{
		  $regs->{s0} = -1;
		}
      _end_
	scmp
	
	loadi %i0 1
	cmp %s0 %i0
      loadd %r0 "We're now in KERNEL code space (ring 3)!"
		
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
    scmp
	cmpf
	  loadd %r0 "Something went awry!"
		
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
		
	  _sl_
	    sleep(5);
	  _end_
	  
	  halt ! Same effect can be reached by invoking interrupt 0x00, but...
	  ! halt will also be used to stop processes run by OSes, so doing
	  ! int 0x00 is more certain to halt the VM if in RINGs 1 or 3
	scmp
	
	loadd %r0 "Attempting to move into BIOS code space (ring 1)..."
	
	mov %a0 %r0
	call print
	call verbose
	free %a0
	
	movv %a0 *BIOS_SPACE
	
	push0x03 %a0
	int 0x03
	pop0x03 %s0
	
	loadi %i0 -1
	cmp %i0 %s0
	  loadd %r0 "Failed to move into BIOS code space (ring 1)!"
	  
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
	scmp
	cmpf
	  loadi %f0 -1
	scmp
	
	cmp %f0 %i0
	  loadd %r0 "Got a good report; checking ring mode..."
	  
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
	  
	  _sl_
	    if($__vmRingMode == 1){
		  $regs->{s0} = 1;
		}else{
		  $regs->{s0} = -1;
		}
      _end_
	scmp
	
	loadi %i0 1
	cmp %s0 %i0
      loadd %r0 "We're now in BIOS code space (ring 1)!"
		
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
    scmp
	cmpf
	  loadd %r0 "Something went awry!"
		
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
		
	  _sl_
	    sleep(5);
	  _end_
	  
	  halt ! Same effect can be reached by invoking interrupt 0x00, but...
	  ! halt will also be used to stop processes run by OSes, so doing
	  ! int 0x00 is more certain to halt the VM if in RINGs 1 or 3
	scmp
	
	loadd %r0 "Attempting to move into USER code space (ring 4)..."
	
	mov %a0 %r0
	call print
	call verbose
	free %a0
	
	movv %a0 *USER_SPACE
	
	push0x03 %a0
	int 0x03
	pop0x03 %s0
	
	loadi %i0 -1
	cmp %i0 %s0
	  loadd %r0 "Failed to move into USER code space (ring 4)!"
	  
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
	scmp
	cmpf
	  loadi %f0 -1
	scmp
	
	cmp %f0 %i0
	  loadd %r0 "Got a good report; checking ring mode..."
	  
	  mov %a0 %r0
	  call userSpacePrint
	  call verbose
	  free %a0
	  
	  _sl_
	    if($__vmRingMode == 4){
		  $regs->{s0} = 1;
		}else{
		  $regs->{s0} = -1;
		}
      _end_
	scmp
	
	loadi %i0 1
	cmp %s0 %i0
      loadd %r0 "We're now in USER code space (ring 4)!"
		
	  mov %a0 %r0
	  call userSpacePrint
	  call verbose
	  free %a0
    scmp
	cmpf
	  loadd %r0 "Something went awry!"
		
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
		
	  _sl_
	    sleep(5);
	  _end_
	  
	  halt ! Same effect can be reached by invoking interrupt 0x00, but...
	  ! halt will also be used to stop processes run by OSes, so doing
	  ! int 0x00 is more certain to halt the VM if in RINGs 1 or 3
	scmp
	
	loadd %r0 "Attempting to move into BIOS code space (ring 1)..."
	
	mov %a0 %r0
	call userSpacePrint
	call verbose
	free %a0
	
	movv %a0 *BIOS_SPACE
	
	push0x03 %a0
	int 0x03
	pop0x03 %s0
	
	loadi %i0 -1
	cmp %i0 %s0
	  loadd %r0 "Failed to move into BIOS code space (ring 1)!"
	  
	  mov %a0 %r0
	  call userSpacePrint
	  call verbose
	  free %a0
	  
	  loadd %r0 "Forcing a move into BIOS code space..."
	  
	  mov %a0 %r0
	  call userSpacePrint
	  call verbose
	  free %a0
	  
	  call returnToBIOSSpace
	  
      loadi %s0 1	  
	scmp
	cmpf
	  loadi %f0 1
	scmp
	
	cmp %f0 %i0
	  loadd %r0 "Got a good report; checking ring mode..."
	  
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
	  
	  _sl_
	    if($__vmRingMode == 1){
		  $regs->{s0} = 1;
		}else{
		  $regs->{s0} = -1;
		}
      _end_
	scmp
	
	loadi %i0 1
	cmp %s0 %i0
      loadd %r0 "We're now in BIOS code space (ring 1)!"
		
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
    scmp
	cmpf
	  loadd %r0 "Something went awry!"
		
	  mov %a0 %r0
	  call print
	  call verbose
	  free %a0
		
	  _sl_
	    sleep(5);
	  _end_
	  
	  halt ! Same effect can be reached by invoking interrupt 0x00, but...
	  ! halt will also be used to stop processes run by OSes, so doing
	  ! int 0x00 is more certain to halt the VM if in RINGs 1 or 3
	scmp
	
	loadd %r0 "Checking ring mode..."
	
	mov %a0 %r0
	call print
	call verbose
	free %a0
	
	_sl_
	  $regs->{i0} = $__vmRingMode;
	_end_
	
	loadd %r0 "Now in RING:"
	appr %r0 %i0
	
	mov %a0 %r0
	call print
	call verbose
	free %a0
	
	free %r0
	free %i0
	free %s0
	
	_sl_
	  sleep(10);
	_end_
	
	ret
	.stop
	
  .__entry:
    call main
	
	halt
	.stop
	
  .end